/*
 * Copyright 2010 Marcin Blazejewski
 *
 * This file is part of Nofate.
 *
 * Nofate is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Nofate is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Nofate. If not, see <http://www.gnu.org/licenses/>.
 *
 */


#include "map.hpp"
#include "attribute.hpp"
#include "thing.hpp"

#include <stdlib.h>
#include <string.h>


load_func(atld_int, Aint);
load_func(atld_float, Afloat);
load_func(atld_str, Astr);
load_func(atld_container, Acontainer);
load_func(atld_terrain, Aterrain);

Aint::Aint(const int v) : value(v) {
}

Aint::Aint(const void **d) : value( (int)d[0] ) {
}

Aint::~Aint() {
}

/*******************************************************************************/

Afloat::Afloat(const float v) : value(v) {
}

Afloat::Afloat(const void **d) : value( *(float*)d[0] ) {
}

Afloat::~Afloat() {
}

/*******************************************************************************/

Astr::Astr(const char *v) : value(v) {
}

Astr::Astr(const void **d) : value( (const char*)d[0] ) {
}

Astr::~Astr() {
}

/*******************************************************************************/

Acontainer::Acontainer(int as, int s, int w) {
    accept_slot = as;
    size_capacity = s;
    weight_capacity = w;
    size_used = 0;
    weight_used = 0;
}

Acontainer::Acontainer(const void **d) {
    Acontainer( (int)d[0], (int)d[1], (int)d[2] );
}

Acontainer::~Acontainer() {
    std::list<Thing*>::iterator i;

    for (i = items.begin(); i != items.end(); i++) {
        delete *i;
    }
}

bool Acontainer::accepts(Thing *t) {    
    // equipment slot - only accept items with same slot type
    if (accept_slot != EQS_NONE) {
        Aint *t_slot = (Aint*)t->attributes["slot"];
        if (t_slot == NULL) return false;
        if (t_slot->value != accept_slot) return false;
    }

    // check size and weight availability
    int t_size = 1; // TODO: get from Thing properties
    int t_weight = 10;

    if (size_capacity > 0)
        if ((size_used + t_size) > size_capacity) return false;

    if (weight_capacity > 0)
         if ((weight_used + t_weight) > weight_capacity) return false;

    return true;
}

void Acontainer::pickup(Thing *itm, Creature *cre) {
    if (!accepts(itm)) return;

    items.push_back(itm);
    if (itm->area) {
        itm->area->remove_thing(itm);
    }

    Attr *a = (Attr*)itm->attributes["container"];
    if (a != NULL) {
        cre->containers.push_back(itm);
    }
}

void Acontainer::drop(Thing *itm, Creature *cre) {
    Acontainer *a = (Acontainer*)itm->attributes["container"];
    vector<Thing*>::iterator i;

    if (a != NULL) {
        cre->containers.erase(i);
    }

#warning TODO Verify the above
#warning TODO Remove itm from self.items list

    itm->x = cre->x;
    itm->y = cre->y;
    cre->area->add_thing(itm);
}


Acontainer* con_find_target(Creature *cre, Thing *itm) {
    Acontainer *con;
    vector<Thing*>::iterator i;

    for (i = cre->containers.begin(); i != cre->containers.end(); i++) {
        con = (Acontainer*)(*i)->attributes["container"];
        
        if (con->accepts(itm)) return con;
    }

    return NULL;
}


/*******************************************************************************/

Aterrain::Aterrain(const int _bg) : bg(_bg) {
}

Aterrain::Aterrain(const void **d) : bg( (int)d[0] ) {
}

Aterrain::~Aterrain() {
}

/*******************************************************************************/

